// File: jmcomic-core/src/main/java/dev/jukomu/jmcomic/util/JmApiAdaptUtils.java
package dev.jukomu.jmcomic.util;

import dev.jukomu.common.util.json.AdvancedMap;
import dev.jukomu.jmcomic.config.JmModuleConfig;
import dev.jukomu.jmcomic.entity.JmAlbumDetail;
import dev.jukomu.jmcomic.entity.JmPhotoDetail;
import dev.jukomu.jmcomic.entity.Triple;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 对应Python的JmApiAdaptTool，负责将移动端API返回值适配为标准实体类。
 */
public class JmApiAdaptUtils {

    // 字段适配器：定义API字段到实体类字段的映射和转换规则
    private static final Map<Class<?>, List<Object>> FIELD_ADAPTER = new ConcurrentHashMap<>();

    static {
        // JmAlbumDetail的适配规则
        FIELD_ADAPTER.put(JmAlbumDetail.class, Collections.unmodifiableList(Arrays.asList(
                "likes", "tags", "works", "actors",
                new String[]{"related_list", "relatedList"},
                "name",
                new String[]{"id", "albumId"},
                new String[]{"author", "authors"},
                new String[]{"total_views", "views"},
                new String[]{"comment_total", "commentCount"}
        )));

        // JmPhotoDetail的适配规则
        FIELD_ADAPTER.put(JmPhotoDetail.class, Collections.unmodifiableList(Arrays.asList(
                "name", "tags",
                new String[]{"series_id", "seriesId"},
                new String[]{"id", "photoId"},
                new String[]{"images", "pageArr"}
        )));
    }

    /**
     * 根据API返回的Map数据和目标实体类类型，解析并适配实体类。
     *
     * @param apiData API返回的原始Map数据
     * @param clazz   目标实体类类型（例如JmAlbumDetail.class, JmPhotoDetail.class）
     * @param <T>     实体类类型
     * @return 解析并适配后的实体类实例
     * @throws IllegalArgumentException 如果不支持的目标类型
     */
    public static <T> T parseEntity(Map<String, Object> apiData, Class<T> clazz) {
        List<Object> adapterRules = getAdapterRules(clazz);
        Map<String, Object> fields = new HashMap<>(); // 用于构建实体类的字段Map

        for (Object rule : adapterRules) {
            String apiField;
            String entityField;
            if (rule instanceof String) {
                apiField = (String) rule;
                entityField = apiField;
            } else if (rule instanceof String[]) {
                String[] ruleArray = (String[]) rule;
                apiField = ruleArray[0];
                entityField = ruleArray[1];
            } else {
                continue; // Skip invalid rule format
            }

            if (apiData.containsKey(apiField)) {
                fields.put(entityField, apiData.get(apiField));
            }
        }

        // 进行后处理适配
        if (JmAlbumDetail.class.isAssignableFrom(clazz)) {
            postAdaptAlbum(apiData, fields);
        } else if (JmPhotoDetail.class.isAssignableFrom(clazz)) {
            postAdaptPhoto(apiData, fields);
        } else {
            throw new IllegalArgumentException("Unsupported entity type for adaptation: " + clazz.getName());
        }

        // 通过反射创建实例并设置字段
        try {
            T instance = clazz.getDeclaredConstructor().newInstance();
            for (Map.Entry<String, Object> entry : fields.entrySet()) {
                try {
                    Field field = clazz.getDeclaredField(entry.getKey());
                    field.setAccessible(true);
                    Object value = convertType(entry.getValue(), field.getType());
                    field.set(instance, value);
                } catch (NoSuchFieldException e) {
                    // Ignore if field doesn't exist in Java class, may be handled by constructor or setter
                }
            }
            return instance;
        } catch (InstantiationException | IllegalAccessException | InvocationTargetException |
                 NoSuchMethodException e) {
            throw new RuntimeException("Failed to create and populate entity instance: " + clazz.getName(), e);
        }
    }

    /**
     * 获取指定实体类的适配规则。
     */
    private static List<Object> getAdapterRules(Class<?> clazz) {
        for (Map.Entry<Class<?>, List<Object>> entry : FIELD_ADAPTER.entrySet()) {
            if (entry.getKey().isAssignableFrom(clazz)) {
                return entry.getValue();
            }
        }
        throw new IllegalArgumentException("No adapter rules found for type: " + clazz.getName());
    }

    /**
     * 对JmAlbumDetail进行后处理适配。
     */
    private static void postAdaptAlbum(Map<String, Object> apiData, Map<String, Object> fields) {
        // episodeList
        List<Map<String, Object>> series = (List<Map<String, Object>>) apiData.getOrDefault("series", Collections.emptyList());
        List<Triple<String, String, String>> episodeList = new ArrayList<>();

        // 处理单章节本子的情况
        if (series.isEmpty()) {
            // 使用 String.valueOf() 安全地将 Object 转换为 String
            String albumId = String.valueOf(fields.get("albumId"));
            String name = String.valueOf(fields.get("name"));
            // 确保 albumId 和 name 不是 "null" 字符串或空的
            if (albumId != null && !"null".equals(albumId) && name != null && !"null".equals(name)) {
                episodeList.add(Triple.of(albumId, "1", name));
            }
        } else {
            for (Map<String, Object> chapter : series) {
                AdvancedMap chapterMap = new AdvancedMap(chapter);
                episodeList.add(Triple.of(
                        String.valueOf(chapterMap.get("id", "0")),
                        String.valueOf(chapterMap.get("sort", "0")),
                        String.valueOf(chapterMap.get("name", ""))
                ));
            }
        }
        fields.put("episodeList", episodeList);

        // 默认值
        fields.putIfAbsent("scrambleId", "0");
        fields.putIfAbsent("pageCount", 0);
        fields.putIfAbsent("pubDate", "");
        fields.putIfAbsent("updateDate", "");
        fields.putIfAbsent("works", Collections.emptyList());
        fields.putIfAbsent("actors", Collections.emptyList());

        // authors: API返回的是author字符串，实体类需要List<String>
        Object authorObj = apiData.get("author");
        if (authorObj instanceof String) {
            fields.put("authors", Collections.singletonList((String) authorObj));
        } else if (authorObj instanceof List) {
            fields.put("authors", ((List<?>) authorObj).stream().map(String::valueOf).collect(Collectors.toList()));
        } else {
            fields.put("authors", Collections.emptyList());
        }

        // tags
        Object tagsObj = apiData.get("tags");
        if (tagsObj instanceof List) {
            fields.put("tags", ((List<?>) tagsObj).stream().map(String::valueOf).collect(Collectors.toList()));
        } else {
            fields.put("tags", Collections.emptyList());
        }
    }

    /**
     * 查找合适的setter方法。
     */
    private static java.lang.reflect.Method findSetter(Class<?> clazz, String setterName, Object value) {
        for (java.lang.reflect.Method method : clazz.getMethods()) {
            if (method.getName().equals(setterName) && method.getParameterCount() == 1) {
                if (value == null || method.getParameterTypes()[0].isInstance(value)) {
                    return method;
                }
            }
        }
        return null;
    }

    /**
     * 对JmPhotoDetail进行后处理适配。
     */
    private static void postAdaptPhoto(Map<String, Object> apiData, Map<String, Object> fields) {
        // sort
        int sort = 1; // 默认值
        List<Map<String, Object>> series = (List<Map<String, Object>>) apiData.getOrDefault("series", Collections.emptyList());
        Object photoIdObj = apiData.get("id");
        if (photoIdObj != null) {
            String photoIdStr = String.valueOf(photoIdObj);
            for (Map<String, Object> chapter : series) {
                AdvancedMap chapterMap = new AdvancedMap(chapter);
                if (Objects.equals(String.valueOf(chapterMap.get("id")), photoIdStr)) {
                    Object sortObj = chapterMap.get("sort");
                    if (sortObj instanceof Number) {
                        sort = ((Number) sortObj).intValue();
                    } else if (sortObj instanceof String) {
                        try {
                            sort = Integer.parseInt((String) sortObj);
                        } catch (NumberFormatException e) {
                            // ignore, use default 1
                        }
                    }
                    break;
                }
            }
        }
        fields.put("sort", sort);

        // dataOriginalDomain
        if (!JmModuleConfig.DOMAIN_IMAGE_LIST.isEmpty()) {
            Random random = new Random();
            fields.put("dataOriginalDomain", JmModuleConfig.DOMAIN_IMAGE_LIST.get(random.nextInt(JmModuleConfig.DOMAIN_IMAGE_LIST.size())));
        } else {
            JmModuleConfig.jmLog("util.api_adapt", "DOMAIN_IMAGE_LIST is empty, cannot set dataOriginalDomain.");
        }

        // tagsString
        Object tagsObj = apiData.get("tags");
        if (tagsObj instanceof String) {
            fields.put("tagsString", (String) tagsObj);
        } else {
            fields.put("tagsString", "");
        }

        // pageArr
        Object imagesObj = apiData.get("images");
        if (imagesObj instanceof List) {
            fields.put("pageArr", ((List<?>) imagesObj).stream().map(String::valueOf).collect(Collectors.toList()));
        } else {
            fields.put("pageArr", Collections.emptyList());
        }

        // 默认值
        fields.putIfAbsent("scrambleId", "0");
        fields.putIfAbsent("seriesId", 0);
    }

    /**
     * 将值转换为目标类型。
     */
    private static Object convertType(Object value, Class<?> targetType) {
        if (value == null) {
            // 对于基本类型，返回其默认值
            if (targetType.isPrimitive()) {
                if (targetType == int.class) {
                    return 0;
                }
                if (targetType == long.class) {
                    return 0L;
                }
                if (targetType == double.class) {
                    return 0.0;
                }
                if (targetType == float.class) {
                    return 0.0f;
                }
                if (targetType == boolean.class) {
                    return false;
                }
                if (targetType == char.class) {
                    return '\u0000';
                }
                if (targetType == byte.class) {
                    return (byte) 0;
                }
                if (targetType == short.class) {
                    return (short) 0;
                }
            }
            return null;
        }
        if (targetType.isInstance(value)) {
            return value;
        }
        if ((targetType == int.class || targetType == Integer.class) && value instanceof Number) {
            return ((Number) value).intValue();
        }
        if ((targetType == int.class || targetType == Integer.class) && value instanceof String) {
            try {
                return Integer.parseInt((String) value);
            } catch (NumberFormatException e) {
                return 0;
            }
        }
        if ((targetType == long.class || targetType == Long.class) && value instanceof Number) {
            return ((Number) value).longValue();
        }
        if (targetType == String.class) {
            return String.valueOf(value);
        }
        return value;
    }
}